package agentePSA;

import java.util.List;
import java.util.LinkedList;

import respsa.EstadoPosicao;
import respsa.ObjectivoPosicao;
import respsa.OperadorGeral;
import respsa.OperadorConcreto;
import simulador.Simulador;
import mecproc.MecProcAA;
import mecproc.No;
import agente.Agente;
import agente.MemElem;
import ambiente.Accao;
import ambiente.Elemento;
import ambiente.Elemento.Tipo;

public class AgenteBDI extends Agente{
	
	private MemElem imagem = new MemElem();
	private MemElem crencas = new MemElem();
	private MemElem desejos = new MemElem();
	private MemElem intencoes = new MemElem();
	private LinkedList<OperadorConcreto> plano = new LinkedList<OperadorConcreto>();
	
	private MecProcAA<EstadoPosicao> mecProcura = new MecProcAA<EstadoPosicao>();
	private OperadorGeral[] operadores = { 
			new OperadorGeral(Accao.Tipo.MOVER, crencas),
			new OperadorGeral(Accao.Tipo.PEGAR, crencas),
			new OperadorGeral(Accao.Tipo.LARGAR, crencas)};
 	

	@Override
	public void iniciar() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void percepcionar() {
		// TODO Auto-generated method stub
		imagem  = this.getSensorPanoramico().detectar();
	}

	@Override
	public void processar() {
		// TODO Auto-generated method stub
		actualizarCrencas();
		if(reconsiderar()){
			gerarOpcoes();
			seleccionarOpcoes();
			planear();
		}
		
	}
	
	@Override
	public void agir() {
		// TODO Auto-generated method stub
		if(!plano.isEmpty())
			this.getActuador().actuar(plano.pollFirst().getAccao());
		
	}
	
	private void actualizarCrencas(){
		crencas.update(imagem);
		Simulador.limparVis(0);
		Simulador.mostrarElementos(crencas, 0);
		
	}
	
	private void gerarOpcoes(){
		desejos.clear();
		
		if(crencas.getAgente().isCarga())
			desejos.putAll(crencas.get(Tipo.BASE,false));
		else
			desejos.putAll(crencas.get(Tipo.ALVO,false));
	}
	
	private void seleccionarOpcoes(){
		intencoes.clear();
		Elemento elem = desejos.getProx(crencas.getAgente().getPosicao());
		if(elem!=null)
			intencoes.put(elem);
	}
	
	private void planear(){
		plano.clear();
		
		EstadoPosicao estIni = new EstadoPosicao(crencas.getAgente().getPosicao());
		
		if(!intencoes.isEmpty()){
			ObjectivoPosicao objectivo = new ObjectivoPosicao(new EstadoPosicao(intencoes.getFirst().getPosicao()));
			LinkedList<No<EstadoPosicao>> solucao= mecProcura.procurar(estIni,objectivo, operadores);
		
			if(solucao!=null){
				
				solucao.remove();
				for(No<EstadoPosicao> est: solucao){
					plano.add((OperadorConcreto) est.getOperador());
				}
				Simulador.limparVis(1);
				List<Accao> accoes = new LinkedList<Accao>();
				for(OperadorConcreto op: plano)
					accoes.add(op.getAccao());
				Simulador.mostrarAccoes(estIni.getInfo(), accoes, 1);
			}
		}
	}
	
	private boolean reconsiderar(){
		return crencas.alteracao();
	}
	
	
	
}
